<!--
    文件选择框
    refer: https://developer.mozilla.org/zh-CN/docs/web/api/file/using_files_from_web_applications
 -->
<style>
    #dropbox {
        width: 100%;
        height: 200px;
        display: grid;
        place-items: center;
        cursor: pointer;
        transition: all 0.5s;
        border-radius: 5px;
    }

    #dropbox:hover {
        transform: scale(1.03);
    }

    .lightgrey {
        background-color: lightgrey;
    }

    .green {
        background-color: #39a705;
        color: #caf6b6;
    }

    .grey {
        background-color: grey;
        color: #b5b5b5;
    }

    .process-bar {
        background-color: #b5b5b5;
        width: 100%;
        height: 5px;
        border-radius: 2px;
        overflow: hidden;
    }

    .process-bar-inner {
        background-color: #39a705;
        width: 0;
        height: 100%;
        transition: all 0.3s;
    }

    .file-info-paragraph>span {
        background-color: lightpink;
        color: darkred;
        padding: 1px 5px;
        border-radius: 4px;
        font-size: 0.8em;
    }

    /* 上传按钮样式 */
    #beginUpload {
        margin-top: 30px;
        padding: 5px 12px;
        transition: all 0.25s;
        border: 0;
    }

    #beginUpload:hover {
        transform: scale(1.1);
        background-color: #39a705;
        color: #caf6b6;
        border-radius: 5px;
        cursor: pointer;
    }

    #beginUpload[disabled]:hover {
        transform: initial;
        background-color: initial;
        color: initial;
        border-radius: initial;
        cursor: initial;
    }

    #fileAssociator {
        padding: 3px 12px;
        min-width: 200px;
    }
</style>
<p>
    <a href="<%= pageUrl %>../">返回文件管理</a>
</p>
<div id="dropbox" class="lightgrey">
    <p>
        点击此处或将文件拖入此处以选择文件<br>
        <!-- 文件个数: <span id="fileNum">0</span>; -->
        文件大小: <span id="fileSize">0</span>
    </p>
</div>
<!-- <input type="file" id="input" multiple onchange="handleFiles(this.files)"> -->
<input type="file" id="fileSelector" style="display: none;">
<p style="font-size: 12px;">
    仅支持 Chrome 内核浏览器
</p>
<div id="file-detail-container" style="display: none;">
    <p style="text-align: left;" class="file-info-paragraph">
        文件名: <span id="file-name"></span><br>
        文件扩展名：<span id="file-ext"></span><br>
        文件名（不含扩展名）：<span id="file-name-no-ext"></span><br>
        文件大小: <span id="file-size"></span><br>
        修改日期: <span id="file-lastModified"></span><br>
        文件SHA1: <span id="file-sha1"></span><br>
    </p>
    <p>计算文件哈希进度</p>
    <div id="processBar1" class="process-bar">
        <div id="processBar1Inner" class="process-bar-inner"></div>
    </div>
    <p>文件上传进度<br><span id="upload-speed"><!-- 上传速度 --></span></p>
    <div id="processBar2" class="process-bar">
        <div id="processBar2Inner" class="process-bar-inner"></div>
    </div>
    <p>关联文件<br><span style="font-size: 12px;">（仅可关联系统中未设置SHA1，或SHA1值相同的文件记录）</span></p>
    <select id="fileAssociator">
        <!-- <option value="0">新建文件</option> -->
    </select>
</div>
<button id="beginUpload" disabled="true">开始上传</button>

<p>
    <input type="checkbox" id="checkbox-auto-upload"><!-- checked -->
    <label for="checkbox-auto-upload" style="font-size: small;">连续上传（上传完成后留在本页）</label>
</p>

<script src="/assets/lib/crypto-js/sha1.js"></script>
<script>
    var file = null;
    var fileInfo = {
        fileName: "",
        fileSize: 0,
        fileType: "",
        lastModified: "",
        fileSha1: "",
        fileExt: "",
        fileNameWithoutExt: "",
    };

    const inputElement = document.getElementById("fileSelector");
    inputElement.addEventListener("change", fileSelectorHandleFiles, false);

    const beginUpload = document.getElementById("beginUpload");
    beginUpload.addEventListener("click", upload);

    //##############################################
    // 选择文件
    //##############################################
    function fileSelectorHandleFiles() {
        const fileList = this.files; /* now you can work with the file list */
        // console.log(fileList);
        handleFiles(fileList);
    }
    async function handleFiles(fileList) {
        updateUI({ isFileEmpty: true });
        if (fileList.length === 0) {
            // 还未选择文件
            return;
        }
        if (fileList.length > 1) {
            swal("一次只能选择1个文件！");
            return;
        }

        // 获取用户选择的文件
        file = fileList[0];
        console.log(file);

        // // 判断用户选择的文件是否为文件夹
        // if (await isFolder(file)) {
        //     swal("不支持文件夹，请选择文件！");
        //     return;
        // }

        // 输出所选文件的总大小
        let nBytes = 0;
        for (let nFileId = 0; nFileId < fileList.length; nFileId++) {
            nBytes += fileList[nFileId].size;
        }
        let sOutput = nBytes + " bytes";
        // optional code for multiples approximation
        const aMultiples = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
        for (nMultiple = 0, nApprox = nBytes / 1024; nApprox > 1; nApprox /= 1024, nMultiple++) {
            sOutput = nApprox.toFixed(2) + " " + aMultiples[nMultiple] + " (" + nBytes + " bytes)";
        }

        // document.getElementById("fileNum").innerHTML = fileList.length;
        document.getElementById("fileSize").innerHTML = sOutput;

        updateUI({ isFileEmpty: false });

        // 记录文件信息
        fileInfo.fileName = file.name;
        fileInfo.fileSize = file.size;
        fileInfo.fileType = file.type;
        fileInfo.lastModified = file.lastModified;
        // 获取文件扩展名：首先按照 . 拆分，然后删掉第一个元素（考虑无扩展名文件），再取出最后一个元素
        let fileNameSplit = file.name.split(".");
        fileNameSplit.shift();
        fileInfo.fileExt = fileNameSplit.pop() || "";
        // 获取文件名（不包含扩展名）
        fileInfo.fileNameWithoutExt = file.name.substr(0, (file.name.length + file.name.lastIndexOf('.')) % (file.name.length));

        // 更新UI
        document.getElementById("file-name").innerHTML = fileInfo.fileName;
        document.getElementById("file-ext").innerHTML = fileInfo.fileExt;
        document.getElementById("file-name-no-ext").innerHTML = fileInfo.fileNameWithoutExt;
        document.getElementById("file-size").innerHTML = sOutput;
        document.getElementById("file-lastModified").innerHTML = new Date(fileInfo.lastModified).toISOString().replace(/T/, ' ').replace(/\..+/, '');

        // 计算文件哈希
        let sha1 = await sha1File(file, (file) => {
            document.getElementById("processBar1Inner").style.width = `${file.sha1_progress}%`;
            // console.log("计算文件哈希 进度", file.sha1_progress);
        });
        fileInfo.fileSha1 = sha1;
        document.getElementById("file-sha1").innerHTML = fileInfo.fileSha1;

        // 获取关联文件下拉框列表并渲染
        getFileAssociatorList(sha1);

        // 完成
        console.log(fileInfo);
    }

    // dropbox 点击时触发 file 的 click 事件
    const fileSelect = document.getElementById("dropbox");
    fileSelect.addEventListener("click", function (e) {
        if (inputElement) {
            inputElement.click();
        }
    }, false);


    //##############################################
    // 使用拖放来选择文件
    //##############################################
    let dropbox = document.getElementById("dropbox");
    dropbox.addEventListener("dragenter", dragenter, false);
    dropbox.addEventListener("dragleave", dragleave, false);
    dropbox.addEventListener("dragover", dragover, false);
    dropbox.addEventListener("drop", drop, false);

    var lastenter = null; // refer: https://www.jianshu.com/p/f96b754032a1

    function dragenter(e) {
        e.stopPropagation();
        e.preventDefault();
        lastenter = e.target; // 记录最后进入的元素
    }

    function dragleave(e) {
        if (lastenter == e.target)
            dropbox.classList.remove('grey');
    }

    function dragover(e) {
        e.stopPropagation();
        e.preventDefault();
        dropbox.classList.add('grey');
    }

    function drop(e) {
        e.stopPropagation();
        e.preventDefault();
        dropbox.classList.remove('grey');

        var dt = e.dataTransfer;
        var files = dt.files;

        console.log("dt", dt.items);
        console.log("dt", dt.items[0]);
        console.log("dt", dt.items[0].webkitGetAsEntry());

        updateUI({ isFileEmpty: true });
        if (dt.items.length > 1) {
            swal("一次只能选择1个文件！");
            return;
        }
        if (dt.items[0].webkitGetAsEntry().isDirectory) {
            swal("不支持文件夹，请选择文件！");
            return;
        }
        handleFiles(files);
    }


    // //##############################################
    // // 判断拖入的文件是否是文件夹 （非 Chrome 内核浏览器逻辑）
    // // 读取文件的第一个字符，如果能够读取成功，那么就是文件，否则就是文件夹
    // // refer: https://segmentfault.com/a/1190000013298317
    // //##############################################
    // async function isFolder(file) {
    //     return await new Promise((resolve, reject) => {
    //         try {
    //             var fileReader = new FileReader();

    //             fileReader.addEventListener('load', function (e) {
    //                 console.log(e, 'load');
    //                 resolve(false);
    //             }, false);

    //             fileReader.addEventListener('error', function (e) {
    //                 console.log(e, 'error，不可以上传文件夹');
    //                 resolve(true);
    //             }, false);

    //             fileReader.readAsDataURL(file.slice(0, 3));
    //         } catch (e) {
    //             console.log(e, 'catch error，不可以上传文件夹');
    //             resolve(true);
    //         }
    //     });
    // }


    //##############################################
    // 更新界面显示
    //##############################################
    function updateUI({ isFileEmpty }) {
        if (isFileEmpty) {
            // 未选择文件
            this.outerHTML = this.outerHTML; // 清除选择的文件
            file = null;
            fileInfo = {};
            document.getElementById("fileSize").innerHTML = "0";
            document.getElementById("processBar1Inner").style.width = 0;
            document.getElementById("processBar2Inner").style.width = 0;
            document.getElementById("file-name").innerHTML = "";
            document.getElementById("file-ext").innerHTML = "";
            document.getElementById("file-name-no-ext").innerHTML = "";
            document.getElementById("file-size").innerHTML = "";
            document.getElementById("file-sha1").innerHTML = "";
            dropbox.classList.remove("green");
            beginUpload.setAttribute("disabled", "true");
            document.getElementById("file-detail-container").style.display = "none";
        } else {
            // 已选择文件
            dropbox.classList.add("green");
            beginUpload.removeAttribute("disabled");
            document.getElementById("file-detail-container").style.display = "";

            // 隐藏文件选择器，避免多次选择文件造成后面计算哈希及上传文件出现混乱
            $("#dropbox").css("transition", "0.3s");
            $("#dropbox").css("height", 0);
            $("#dropbox").css("opacity", 0);
            setTimeout(function () {
                $("#dropbox").css("display", "none");
            }, 300);
        }
    }

    //##############################################
    // 获取预授权URL
    //##############################################
    function upload() {
        if (!file) {
            swal("您还未选择文件！");
            return;
        }
        var postParams = {
            token: localStorageUtils.getToken(),
            expireMinute: 30,
            fileName: fileInfo.fileNameWithoutExt,
            fileSize: fileInfo.fileSize,
            // fileType: fileInfo.fileType,
            lastModified: fileInfo.lastModified,
            fileSha1: fileInfo.fileSha1,
            fileExt: fileInfo.fileExt,
            fileId: $("#fileAssociator").val() // 关联的文件ID，创建新文件则为0
        };
        console.log(postParams);
        // 获取预授权URL
        postRequest("/file/object/cos/put", postParams)
            .then(function (response) {
                var axiosData = response.data;
                var status = axiosData.status;
                var data = axiosData.data;
                if (status === "success") {
                    console.log("data", data);
                    // 取得预授权URL，使用该URL进行文件上传
                    uploadFile(file, data.url, data.fileId, data.fileObjectId);
                } else {
                    if (data.errCode == "60001") {
                        // 文件已存在于对象存储中
                        console.log(`出错啦！${data.errMsg} (错误码: ${data.errCode})`);

                        // 再次发送请求，查询这个已存在文件的 fileId
                        postRequest("/file/getFileByHash", { token: localStorageUtils.getToken(), fileSha1: fileInfo.fileSha1 })
                            .then(function (responseData) {
                                var axiosData = responseData.data;
                                var status = axiosData.status;
                                var data = axiosData.data;
                                if (status === "success") {
                                    console.log(data);
                                    if (data) {
                                        // 查询到之后，询问用户是否跳转到文件详情页
                                        var isRedirect = confirm(`文件已存在，是否前往查看详情？\n（文件ID: ${data.id}）`);
                                        if (isRedirect)
                                            location.href = `<%= pageUrl %>../detail?fileId=${data.id}`;
                                    } else {
                                        // 对象存储中存在该文件，但是系统数据库中找不到
                                        swal("出错啦！该文件已存在于腾讯云对象存储中，但是系统中不存在")
                                    }
                                } else {
                                    swal(`出错啦！${data.errMsg} (错误码: ${data.errCode})`);
                                }
                            }).catch(function (error) {
                                console.log(error);
                                swal("无法连接到服务器，请检查网络连接！");
                            });
                    } else {
                        swal(`出错啦！${data.errMsg} (错误码: ${data.errCode})`);
                    }
                }
            }).catch(function (error) {
                console.log(error);
                swal("无法连接到服务器，请检查网络连接！");
            });
    }

    //##############################################
    //传入预授权 URL ，将文件上传到这个地址
    //##############################################
    function uploadFile(file, preSignedUrl, fileId, fileObjectId) {
        // refer: https://cloud.tencent.com/document/product/436/35651

        // 存储上次更新上传进度和速度时，时间和已上传字节 （用于计算上传进度和上传速度）
        var sTime = new Date().getTime(), sLoaded = 0;

        // 获取到 Url 后，前端可以这样 ajax 上传
        var xhr = new XMLHttpRequest();
        xhr.open('PUT', preSignedUrl, true);
        xhr.upload.onprogress = function (e) {
            // e.lengthComputable是一个布尔值,表示当前上传的资源是否有可计算的长度
            if (e.lengthComputable) {
                // 计算出上传的进度
                // e.loaded 已传输的字节
                // e.total 需传输的总字节
                var procentComplete = Math.ceil((e.loaded / e.total) * 100);

                // 距离上次更新界面显示经过的毫秒数 & 上传的文件大小
                let timeSpan = new Date().getTime() - sTime;
                let loadedSpan = e.loaded - sLoaded;

                // 这段时间内的上传速度
                let speed = loadedSpan * 1000 / timeSpan; // 1000: 毫秒 转 秒

                // 更新 sTime, sLoaded
                sTime = new Date().getTime();
                sLoaded = e.loaded;

                // 输出所选文件的总大小
                let nBytes = speed;
                let sOutput = nBytes + " bytes/s";
                // optional code for multiples approximation
                const aMultiples = ["KiB/s", "MiB/s", "GiB/s", "TiB/s", "PiB/s", "EiB/s", "ZiB/s", "YiB/s"];
                for (nMultiple = 0, nApprox = nBytes / 1024; nApprox > 1; nApprox /= 1024, nMultiple++) {
                    sOutput = nApprox.toFixed(2) + " " + aMultiples[nMultiple];
                }

                // 更新界面显示
                document.getElementById("processBar2Inner").style.width = `${procentComplete}%`;
                $("#upload-speed").html(`上传进度: ${procentComplete.toFixed(0)}%，上传速度：${sOutput}`);
                console.log("上传进度", procentComplete);
            }
        };
        xhr.onload = function (e) {
            console.log('上传成功', xhr.status, xhr.statusText);
            // 等待进度条走到 100% 否则小文件进度条还没有走完就提示上传完成会让人感觉有点奇怪
            setTimeout(function () {
                // 上传成功触发一次 “刷新文件对象上传状态”，避免因为云函数回调不成功导致文件对象上传状态没有及时更新
                refreshFileObjectStatus(fileObjectId, function () {
                    swal("上传成功！").then(function () {
                        if ($("#checkbox-auto-upload").is(":checked")) {
                            window.location.reload();
                        } else {
                            // location.href = "<%= pageUrl %>../";
                            location.href = "<%= pageUrl %>../detail?id=" + fileId;
                        }
                    });
                });
            }, 300);
        };
        xhr.onerror = function (e) {
            swal("上传失败，请检查网络连接并重试！").then(function () {
                location.reload();
            });
            console.log('上传出错', xhr.status, xhr.statusText);
        };
        xhr.send(file); // file 是要上传的文件对象
    }
</script>
<script>
    // 关联文件下拉框列表
    function getFileAssociatorList(fileSha1) {
        var fileAssociator = document.getElementById("fileAssociator");
        // 下拉框列表
        postRequest("/file/list/MatchfileHashWithNullValue", { token: localStorageUtils.getToken(), fileSha1: fileSha1 })
            .then(function (responseData) {
                var axiosData = responseData.data;
                var status = axiosData.status;
                var data = axiosData.data;
                if (status === "success") {
                    // console.log(data);
                    // 数据进行转换
                    var optionHTML = "";
                    for (var i = 0; i < data.length; i++) {
                        const element = data[i];
                        optionHTML += `<option value="${element.id}">[${element.id}] ${element.fileName}.${element.fileExt}</option>`;
                    }
                    // 渲染到下拉框内
                    // fileAssociator.innerHTML += optionHTML;
                    fileAssociator.innerHTML = `<option value="0">新建文件</option>` + optionHTML;
                } else {
                    swal(`出错啦！${data.errMsg} (错误码: ${data.errCode})`);
                }
            }).catch(function (error) {
                console.log(error);
                swal("无法连接到服务器，请检查网络连接！");
            });
    }
</script>
<script>
    // 刷新文件对象上传状态
    async function refreshFileObjectStatus(fileObjectId, callback) {
        postRequest("/file/object/refreshFileObjectStatus", { token: localStorageUtils.getToken(), fileObjectId: fileObjectId })
            .then(function (responseData) {
                var axiosData = responseData.data;
                var status = axiosData.status;
                var data = axiosData.data;
                if (status === "success") {
                    // console.log(data);
                    if (callback)
                        callback();
                } else {
                    swal(`出错啦！${data.errMsg} (错误码: ${data.errCode})`);
                }
            }).catch(function (error) {
                console.log(error);
                swal("无法连接到服务器，请检查网络连接！");
            });
    }
</script>